#include <iostream>
#include <limits>
#include <fstream>
#include <stdlib.h>
#include <sstream>
#include <string>
#include <vector>
#include <map>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <libgen.h>
#include <sys/shm.h>

#include "handler.h"
using namespace std;

#define SYSTEM_FILE_MODE 1
#define LOCAL_FILE_MODE 2
//#define _debug_in_VS_

#ifndef _debug_in_VS_
char *ifcfg_file = SYSTEM_IFCFG_FILE;
int file_mode = SYSTEM_FILE_MODE;
const char *GPS_file = "/proc/GPS";
extern const char *Config_file;

#else
const char *ifcfg_file = "ifcfg-eth0.txt";
const char *GPS_file = "testGPS.txt";
const char *Config_file = "testConfig.xml";

#endif

/*********************************************/
//some default settings
const int number_log = 50;

//This should be changed when the special board is used
//It's the default file /etc/sysconfig/network-script/ifcfg-eth0
const string default_ifcfg_eth0("# Advanced Micro Devices [AMD] 79c970 [PCnet32 LANCE]\n"
								"DEVICE=eth0\n"
								"BOOTPROTO=static\n"
								"BROADCAST=192.168.168.255\n"
								"IPADDR=192.168.168.139\n"
								"NETMASK=255.255.255.0\n"
								"GATEWAY=192.168.168.1\n"
								"NETWORK=192.168.168.0\n"
								//"HWADDR=00:0C:29:67:5A:F7\n"
								"ONBOOT=yes\n"
								"TYPE=Ethernet\n"
								);
/*********************************************/

//used for ip configuration
bool ip_flag = false;
vector<string> ifcfg;

// use share memory to sync ptpflag
int shmid;
int *ptpflag;
key_t shmkey;

/**
 * Convert int to string
 */
string itos(int i)
{
	stringstream s;
	s<<i;
	return s.str();
}

/************************************************************************/
/**
 * search the file to find the key, and get its val.
 * if the key can't be found, return -1;
 * else return 0;
*/
/************************************************************************/
int get_property(ifstream &file, string &key, string &val)
{
	if(!file)
		return -1;
	file.seekg(ios::beg);
	string str;
#if 1
	while(!file.eof()) {
		getline(file,str);
		if(str.size() == 0)
			continue;
		string::iterator it_beg = str.begin(),it_cur = str.begin();
		//find the first =
		while(it_cur != str.end() && *it_cur != '=')
			++it_cur;
		if(it_cur == str.end())
			continue;
		string tmp(it_beg,it_cur);
		++it_cur;
		if(tmp == key) {
			val = string(it_cur,str.end());
			return 0;
		}
	}
#endif
	return -1;
}

/************************************************************************/
/**
 * Change the settings according to the information in file.
 * Settings include:
 * 1, ip mode
 * 2, ip
 * 3, netmask
 * 4, gateway
*/
/************************************************************************/
void update_settings(ifstream &file, bool init = false)
{
	IP ip;
	memset(&ip, 0, sizeof(ip));
	const char *ptpflagfile = "/etc/PTP/FLAG";
	
	/*1, change the ip mode*/
	string key_IpMode("BOOTPROTO"),value_IpMode;
	//默认使用static方式获取ip地址
	if(get_property(file,key_IpMode,value_IpMode) < 0) {
		#ifdef _debug_	
		cout << "				Sorry, can't find which method is used to get IP, using static" << endl;
		#endif
		value_IpMode = "static";
	}
	if(value_IpMode == string("dhcp")) {
		/*add the code to start the dhcp*/
		if(system("/sbin/udhcpc") < 0) {
			cout << "				Sorry, can't enable DHCP!" << endl;
		}
		return;
	}
	else {
		/*add the code to forbid dhcp and start the static*/
		cout << "				Static method is used to get IP!" << endl;
	}

	/*2, change the ip, netmask and gateway*/
	if(!init){
		string key_Ip("IPADDR"),key_NetMask("NETMASK"),key_Gateway("GATEWAY"),value_Ip,value_Netmask,value_Gateway;
		if(get_property(file,key_Ip,value_Ip) < 0) {
			#ifdef _debug_
			cout << "				Sorry, can't find the IPADDR in the local ifcfg file, " << endl;
			cout << "				using 0.0.0.0" << endl;
			#endif
			value_Ip = "0.0.0.0";
		}
		if(get_property(file,key_NetMask,value_Netmask) < 0) {
			#ifdef _debug_
			cout << "				Sorry, can't find the NETMASK in the local ifcfg file, " << endl;
			cout << "				using 255.255.255.0" << endl;
			#endif
			value_Netmask = "255.255.255.0";
		}
		if(get_property(file,key_Gateway,value_Gateway) < 0) {
			#ifdef _debug_
			cout << "				Sorry, can't find the GATEWAY in the local ifcfg file, " << endl;
			cout << "				using 0.0.0.1" << endl;
			#endif
			value_Gateway = "0.0.0.1";
		}

		strcpy(ip.ipaddr,value_Ip.c_str());
		strcpy(ip.netmask,value_Netmask.c_str());
		strcpy(ip.gateway,value_Gateway.c_str());

		// We should kill ptpd2 progress before change ip address
		// 启动ptpd2由startptpd2程序负责
		system("killall ptpd2");
		*ptpflag = 0;

		//通过ioctl的方式修改ip地址，子网掩码和网关
		if(!ip_config_ioctl(&ip))
			cout << "				Set ip, netmask, gateway success." << endl;
	}

	/*End of this function*/
}

/************************************************************************/
/* 
initialization of the telnet, three operations are executed in the initialization:
1, check if the system default ip-config file(/etc/sysconfig/network-script/ifcfg-eth0) exists.
	if it exists, end the initialization;
	else continue the next steps.
2, check if the local file ip-config file(./ifcfg-eth0) exists.
	if it exists, continue the next step;
	else using the default content to create a new file;
3, use the content in the local file to update the settings.
*/
/************************************************************************/
void initial_settings()
{
	/*step 1: check if the system default file exists.*/
	ifstream file(SYSTEM_IFCFG_FILE,ios::in);
	if(!file.is_open()) {//系统配置文件不存在
		#ifdef _debug_	
		cout << "				System IP configure file doesn't exist, " << endl;
		cout << "				using the local file!" << endl;
		#endif
		ifcfg_file = LOCAL_IFCFG_FILE;
		file_mode = LOCAL_FILE_MODE;
		file.open(LOCAL_IFCFG_FILE,ios::in);
		/*step 2: check if local file exists.*/
		//本地配置文件不存在执行以下代码段，而当配置文件存在时，则不做处理
		//如果本地配置文件存在但是里边内容的格式不正确还未做考虑
		//为了提高代码稳定性，我们在文件系统中创建了LOCAL_IFCFG_FILE，保证LOCAL_IFCFG_FILE一定存在
		if(!file.is_open()) {
			#ifdef _debug_	
			cout << "				Local IP configure file does't exist, " << endl;
			cout << "				trying creating a new one using the default settings!" << endl;
			#endif
			//創建配置文件的目錄和文件，并往文件中寫入默認配置信息
			string ifcfg_dir = dirname(strdup(LOCAL_IFCFG_FILE));
			string mkdir_command = "mkdir -p " + ifcfg_dir;
			system(mkdir_command.c_str());

			ofstream outfile;
			outfile.open(LOCAL_IFCFG_FILE);
			if (outfile.fail()) cout << "Failed to create file " << LOCAL_IFCFG_FILE << "!\n";
			outfile << default_ifcfg_eth0;
			outfile.close();

			outfile.open(Config_file, ios::in);
			if (outfile.fail()) {
				cout << "Failed to create file " << Config_file << "!\n";
				if( reset_config() < 0 ) return;
			}
			outfile.close();
		}
	}
	else {	//系统配置文件存在
		ifcfg_file = SYSTEM_IFCFG_FILE;
		file_mode = SYSTEM_FILE_MODE;
		return;
	}

	/*step 3: use the local file to update the settings.*/
	ifstream file_tmp(ifcfg_file,ios::in);
	update_settings(file_tmp, true);
	file_tmp.close();
	file.close();

	//设置共享存储，和cleanlog协作
	shmkey = ftok(PTP_FLAG_FILE, 0);
	if ((shmid = shmget(shmkey, 0, SHM_MODE)) < 0) perror("shmget error");
	if ((ptpflag = (int *)shmat(shmid, 0, 0)) == (int *)-1) perror("shmat error");
}


/************************************************************************/
/**
 * 验证输入的是数字ֵ
 */
/************************************************************************/
int input_number(istream &input)
{
	//input a leagal number, or cout << "				>>>"
	int i;
	string str;
	bool flag = false;

	while(!flag) {
		//check if there is '\n' in the buffer of the istream
		getline(input,str);
		while(str.empty()) {
			input.clear();
			while(input.peek() == '\n') {
				input.ignore();
				cout << "				>>>";
				cout.flush();
			}
			getline(input,str);
		}

		stringstream sstr;
		sstr << str;
		sstr >> i;
		if(sstr.fail()) {
			//转换失败，flag为false，会一直提示输入，直到用户输入的数据能够转化为int类型
			sstr.clear();
			cout << "				illegal input!" << endl;
			cout << "				>>>";
		}
		else
			flag = true;
	}
	return i;
}

/************************************************************************/
/**
 * Read the content of ifconfig file into the memory for potential processing.
 */
/************************************************************************/
static int Read_ifcfg(const char *filename)
{
	ifstream file(filename,ios::in);
	if(!file) 
		return -1;
	string str;
	file.seekg(ios::beg);
	while(!file.eof()) {
		getline(file,str);
		if(str.size() == 0)
			continue;
//		str += '\n';
		ifcfg.push_back(str);
	}
	file.close();
	return 0;
}

/************************************************************************/
/**
 * input a legal IP address
 * the format must agree with ***.***.***.***,such as 192.168.168.212
 * return:
 * 	0:	input a IP address successfully
 * 	-1:	IP illegal
 *	-2:	q, quit
 */
/************************************************************************/
static int input_ip_address(string &str)
{
	string t_str;
	getline(cin,t_str);
	while (t_str.empty())
	{
		cin.clear();
		while(cin.peek() == '\n')
			cin.ignore();
		getline(cin,t_str);
	}
	string::iterator it = t_str.begin();
	
	//get rid of the space and enter at the beginning of the string
	while(*it == ' ' || *it == '\n')
		++it;

	//quit,用户输入q，表示放弃输入ip地址，返回-2
	if(*it == 'q')
		return -2;

	str.clear();
	str.insert(str.end(),it,t_str.end());
	
	//add the checking format code here
	//first, check the position and number of '.'
	vector<string::iterator> it_point;
	it_point.push_back(str.begin());
	it = str.begin();
	while(it != str.end()) {
		if(*it >= '0' && *it <= '9')
			++it;
		else if(*it == '.')
			it_point.push_back(++it);
		else
			return -1;
	}
	it_point.push_back(str.end());
	//保证字符串中.的个数为3
	if(it_point.size() != 5)
		return -1;

	//保证每个分割段的值为0-255
	vector<int> ip_val(4);
	for(int i=0; i<4; ++i) {
		stringstream sstr;
		sstr << string(it_point[i],it_point[i+1]);
		sstr >> ip_val[i];
		if(sstr.fail())
			return -1;
		if(ip_val[i] < 0 || ip_val[i] > 255)
			return -1;
	}
	return 0;
}

/************************************************************************/
/**
 * find the key in the content, and change its value
 * if can't find the key, then add a new line with the key and value in it
 */
/************************************************************************/
int change_property(vector<string> &content, const char *key, const char *val)
{
	//find the key in the content
	const string key_str(key);
	for(vector<string>::iterator it = content.begin(); it != content.end(); ++it) {
		string::iterator it_beg = it->begin(),it_cur = it->begin();
		//find the first =
		while(it_cur != it->end() && *it_cur != '=')
			++it_cur;
		if(it_cur == it->end())
			continue;
		string tmp(it_beg,it_cur);
		if(tmp == key_str) {
			tmp =tmp + '=' + val;
			*it = tmp;
			return 0;
		}
	}

	//if can't find the key, then add the key-value in the end of the content
	string tmp(key_str);
	tmp = tmp + '=' + val;
	content.push_back(tmp);
	return 0;
}


/**
 * IP分配的方式，static还是DHCP
 */
int handle_ipconfig_mode(void)
{
	if(ifcfg.size() == 0) {
		if(Read_ifcfg(ifcfg_file) < 0) {
			#ifdef _debug_	
			cout << "				Please make sure the file " << ifcfg_file << " exist!" << endl;
			#endif
			return -1;
		}
	}
	ip_flag = true;
	cout << "				Please input 1 to choose the DHCP or " << endl;
	cout << "				input 2 to choose the static mode to config IP:" << endl;
	int mode;
	while(1) {
		mode = input_number(cin);
		if(mode == 1) {
			change_property(ifcfg,"BOOTPROTO","dhcp");
			cout << "				Select DHCP successfully!" << endl << endl << endl;
			return 0;
		}
		if(mode == 2) {
			change_property(ifcfg,"BOOTPROTO","static");
			cout << "				Select the static mode to config IP successfully!" << endl << endl << endl;
			return 0;
		}
		cout << "				Please input legal number, 1 to choose DHCP, " << endl;
		cout << "				2 to choose static mode:" << endl;
	}	
	return 0;
}


/**
 * 修改ip地址ַ
 */
int handle_ip_address(void)
{
	if(ifcfg.size() == 0) {
		//如果ifcfg为空，表明还未从ip配置文件中ip读取配置信息
		//所以需要先去读取配置文件信息
		if(Read_ifcfg(ifcfg_file) < 0) {
			#ifdef _debug_	
			cout << "				Please make sure the file " << ifcfg_file << " exist!" << endl;
			#endif
			return -1;
		}
	}

	//其次需要判断用户输入的ip地址是否规范
	cout << "				Input IP>>>";
	string str;
	if(input_ip_address(str) < 0)
	{
		cout << "				Your input is illegal. Please provide a legal ip adress," << endl;
		cout << "				such as 192.168.168.212" << endl;
		return -1;
	}
	ip_flag = true;
	//修改ifcfg（vector）中的ip地址信息，此时还未将修改后的ip地址写入到配置文件中
	change_property(ifcfg,"IPADDR",str.c_str());
	return 0;
}

/**
 * 修改掩码，类似handle_ip_address
 */
int handle_netmask(void)
{
	if(ifcfg.size() == 0) {
		if(Read_ifcfg(ifcfg_file) < 0) {
			#ifdef _debug_	
			cout << "				Please make sure the file " << ifcfg_file << " exist!" << endl;
			#endif
			return -1;
		}
	}

	cout << "				Input MASK>>>";
	
	string str;
	if(input_ip_address(str) < 0)
	{
		cout << "				Please input a legal netmask," << endl;
		cout << "				such as 255.255.255.0" << endl;
		return -1;
	}
	ip_flag = true;
	change_property(ifcfg,"NETMASK",str.c_str());
	return 0;
}

/**
 * 修改网关,类似handle_ip_address
 */
int handle_gateway(void)
{
	if(ifcfg.size() == 0) {
		if(Read_ifcfg(ifcfg_file) < 0) {
			#ifdef _debug_	
			cout << "				Please make sure the file " << ifcfg_file << " exist!" << endl;
			#endif
			return -1;
		}
	}
	cout << "				Input GW>>>" ;
	string str;
	if(input_ip_address(str) < 0)
	{
		cout << "				Your input is illegal. Please provide a legal gateway," << endl;
		cout << "				such as 192.168.168.1" << endl;
		return -1;
	}
	ip_flag = true;
	change_property(ifcfg,"GATEWAY",str.c_str());
	return 0;
}

/************************************************************************/
/**
 * Reserved
 */
/************************************************************************/
int handle_SNMP(void)
{
	while(1){
		cout << "				Sorry, this function is not supported now!" << endl;
		if(handle_quit()) break;
	}
	return 0;
}

/************************************************************************/
/**
 * display the latest number_log logs in the file log_file;
 */
/************************************************************************/
int handle_watch(void)
{
//	cout << "				Displaying the latest 50 logs:" << endl;
	//ate, seek to the end of this file
	while(1){
		ifstream fstr_log(LOG_FILE,ios::in | ios::binary);
		string str;
		vector<string> vstr(number_log);
		if(!fstr_log) {
			#ifdef _debug_
			cout << "				Open file " << log_file << " failed, please check if the file exists!" << endl;
			#endif
			return -1;
		}
		fstr_log.seekg(ios::beg);
		int i = -1;
		while(!fstr_log.eof()) {
			getline(fstr_log,str);
			if(str.size() == 0)
				continue;
			str += '\n';
			if(str[0] == ' ') {
				if(i == -1)
					vstr[++i] = str;
				else
					vstr[i] += str;
			}
			else {
				i = (i+1) % number_log;
				vstr[i] = str;
			}
		}
		fstr_log.close();
		if(i == -1) {
			cout << "				The log file is empty." << endl;
			return 0;
		}
		cout << "				The latest log is:" << endl;
		for(int j=0; j<number_log; ++j) {
			// 为了显示的log是最后的log_number行信息，这边的i是关键
			// i记录了vstr中最后log_number行的顺序
			i = (i+1)%number_log;
			//if the vstr[i] is empty, then there is no log information
			if(vstr[i].size() == 0)
				continue;
			cout << j+1 << ":" << vstr[i];
		}
		cout << endl << endl << endl;
		if(handle_quit()) break;
	}
	return 0;
}

/**
 * 发送频率处理函数
 */
int handle_frequency(void)
{
	cout << "				Input send frequency>>>";
	string str_fre;
	cin >> str_fre;

	return set_config("Frequency",str_fre);
}

/**
 * Peer-to-Peer还是End-to-End
 * 使用802.3协议还是UDP/IP
 */
int handle_mode(void) {
	cout << "				set send mode to \n"
			"				1:Peer-to-Peer & 802.3\n"
			"				2:End-to-End & 802.3\n"
			"				3:Peer-to-Peer & UDP/IP\n"
			"				4:End-to-End & UDP/IP\n";
	cout << "				>>>";
	int mode = input_number(cin);

	if (mode == 1 || mode == 2 || mode == 3 || mode == 4) {
		string mode_str = itos(mode);
		if ( set_config("Mode", mode_str) == 0 ) return 0;
		else return -1;
	} else {
		cout << "				invalid input." << endl;
		return -1;
	}
}

/**
 * 显示当前选用的GPS信号
 */
int handle_gpsinput(void)
{
	ifstream file_gps(GPS_file,ios::in | ios::binary);
	if(!file_gps) {
		#ifdef _debug_
		cout << "				open GPS file:" << GPS_file << " failed, " << endl;
		cout << "				please make sure this file exists!" << endl;
		#endif
		return -1;
	}
	int type_of_input;
	file_gps >> type_of_input;
	if(file_gps.fail()) {
		#ifdef _debug_
		cout << "				File format error: the content doesn't agree with the protocol!" << endl;
		#endif
		return -1;
	}
	if(type_of_input == 0)
		cout << "				NMEA0183 signal is chosen for processing!" << endl;
	else if(type_of_input == 1)
		cout << "				IRIG-B signal is chosen for processing!" << endl;
	else
		cout << "				Unknown signal, please check the format of the file" << endl;
	file_gps.close();
	return 0;
}

/**
 * 恢复默认配置信息处理
 */
int handle_default(void)
{
	cout << "				The default setting is:" << endl;
	cout << "				BROADCAST: 192.168.168.255\n"
		"				IPADDR: 192.168.168.139\n"
		"				NETMASK: 255.255.255.0\n"
		"				GATEWAY: 192.168.168.1\n"
		"				Send frequency: 1\n"
		"				Mode: Peer-to-Peer & UDP/IP" << endl;
	cout << "				Recover to factory settings" << endl;
	cout << "				Are you sure to reset the settings? (y/n)" << endl;
	cout << "				>>>";
	cin.clear();
//	cin.ignore(numeric_limits <streamsize>::max(),'\n');;
	while(cin.peek() == '\n')
		cin.ignore();
	char c;
	cin >> c;
	if(c != 'y') {
		cout << "				No change happened." << endl;
		return 0;
	}
	//reset the ip file
	ofstream file(ifcfg_file,ios::out | ios::trunc);
	if(!file) {
		#ifdef _debug_
		cout << "				open file " << ifcfg_file << " failed when reset the settings!" << endl;
		#endif
		cout << "				No change happened." << endl;
		return -1;
	}
	file << default_ifcfg_eth0;
	file.close();
	ip_flag = false;
	ifcfg.clear();
	cout << "				Reset the ip settings successfully!" << endl;

	if( reset_config() < 0 ) return -1;

	{
		ifstream file(ifcfg_file,ios::in);
		update_settings(file);
		file.close();
	}

	return 0;
}

/**
 * 保存配置处理
 */
int handle_save(void)
{
	cout << "				Do you want to save your settings ?(y/n)" << endl;
	cout << "				>>>";
	while(1){
		cin.clear();
	//	cin.ignore(numeric_limits <streamsize>::max(),'\n');;
		while(cin.peek() == '\n')
			cin.ignore();
		char c;
		cin >> c;
	
		if(c == 'y' || c == 'Y') {
			//需要保存变更，并立即生效
			//check if there are changes about IP
			if(ip_flag) {
				ofstream file(ifcfg_file,ios::out | ios::trunc);
				if(!file) {
					#ifdef _debug_
					cout << "				open file " << ifcfg_file << " failed!" << endl;
					#endif
					return -1;
				}
				for(vector<string>::iterator it = ifcfg.begin(); it != ifcfg.end(); ++it)
					file << *it << endl;
				ifcfg.clear();
				ip_flag = false;
				file.close();
				{
					ifstream file_in(ifcfg_file,ios::in);
					update_settings(file_in);
					file_in.close();
				}
				
	//			system("/sbin/service network restart");			
			}
			cout << "				Save IP settings successfully!" << endl;
			
			//save xml file
			if( save_config() < 0 ) return -1;

			break;
		}
		else if(c == 'n' || c == 'N') {
			//放弃对xml文件的修改
			abort_save_config();
			ip_flag = false;
			ifcfg.clear();
			break;
		} else {
			cout << "				Invalid input, retry again." << endl;
			continue;
		}
	}
	return 0;
}

int handle_quit(void){
	cout << "				Do you want to go back to main menu?(y/n)" << endl;
	cout << "				>>>";
	while(1){
		cin.clear();
		while(cin.peek() == '\n')
			cin.ignore();
		char c;
		cin >> c;
		if(c == 'y' || c == 'Y') return 1;
		else if (c == 'n' || c == 'N') return 0;
		else {
			cout << "				Invalid input, retry again." << endl;
			continue;
		}
	}
	return 1;
}

/**
 * 获取Config.xml中的信息并显示
 */
int getIEEEInfo(void) 
{
	//获取Frequency
	cout << "				Send Frequency:" << get_config("Frequency") << endl;

	//获取Mode，运行模式分为p2p和e2e，802.3和UDP/IP
	string mode_value;
	if( !(mode_value = get_config("Mode")).empty() ) {
		(mode_value.compare("1") == 0) ? cout << "				Mode: Peer-to-Peer & 802.3" << endl :
		(mode_value.compare("2") == 0) ? cout << "				Mode: End-to-End & 802.3" << endl :
		(mode_value.compare("3") == 0) ? cout << "				Mode: Peer-to-Peer & UDP/IP" << endl :
		(mode_value.compare("4") == 0) ? cout << "				Mode: End-to-End & UDP/IP" << endl :
		cout << "Unkown mode" << endl;
		return 0;
	}
	else return -1;	//mode == NULL
}

/**
 * 显示ip地址信息以及sync报文发送频率和当前运行模式等信息
 */
int handle_info(void)
{
	cout << "				Here are the current settings' information:" << endl;
	print_ip();
	getIEEEInfo();

	return 0;
}

int handle_help(void)
{
	cout << "				A number is enough for your choice. " << endl;
	cout << "				For example, if you want to change settings, " << endl;
	cout << "				just input the number 2 and enter like the following:" << endl;
	cout << "				\">>>2\"" << endl;
	cout << "				Then you can change settings according to the advices." << endl;
	return 0;
}

/**
 * 处理配置文件（函数命名有点问题）
 */
int handle_ipconfig(void)
{
	while (1)
	{
		if(handle_ip_address() < 0) {
			cout << "				Change IP address error!" << endl;
			break;
		}
		if(handle_netmask() < 0) {
			cout << "				Change netmask error!" << endl;
			break;
		}
		if(handle_gateway() < 0) {
			cout << "				Change gateway error!" << endl;
			break;
		}
		if(handle_frequency() < 0) {
			cout << "				Change send frequency error!" << endl;
			break;
		}
		if( handle_mode() < 0 ) {
			cout << "				Change mode error!" << endl;
			break;
		}
		if(handle_save() < 0) {
			cout << "				Save error!" << endl;
			break;
		}
		if(handle_quit()) break;
		else continue;
	}
	return 0;
}

/**
 * 单播还是多播,已经不用，注释掉
 */
/*
int handle_castmode(void)
{
	// input information
	cout << "				cast mode:" << endl;
	cout << "				set cast mode to (1:multi-cast\t2:unicast\t3 to quit)" << endl;
	cout << "				>>>";
	int c = input_number(cin);
	string t_str;
	vector<string> ip_buf;
	int ret;

	process the input

	//q to quit
	if(c == 3)
		return 0;

	//muti cast mode, input some ip address, and store it in ip_buf
	else if(c == 1){
		//multi cast mode, input the ip address
		cout << "				Please input the cast IP, with q to quit" << endl;
		cout << "				>>>";
		while(1){
			if((ret = input_ip_address(t_str)) < 0) {
				if(ret == -2)
					break;
				else {
					cout << "				illegal ip input, please input a legal one" << endl;
					cout << "				>>>";
				}
			}
			else
				ip_buf.push_back(t_str);
		}
	}

	//unicast mode, input one ip address, and store it in ip_buf
	else if(c == 2){
		//add processing code
		cout << "				Please input one IP, with q to quit" << endl;
		cout << "				>>>";
		while(1){
			if((ret = input_ip_address(t_str)) < 0) {
				if(ret == -2)
					break;
				else {
					cout << "				illegal ip input, please input a legal one" << endl;
					cout << "				>>>";
				}
			}
			else {
				ip_buf.push_back(t_str);
				break;
			}
		}
	}

	//invalid input
	else {
		cout << "				invalid input." << endl;
		return 0;
	}

	print the input information to the user
	if(ip_buf.empty()) {
		cout << "				No IP is provided!" << endl;
		return -1;
	}
	cout << "				Your input IP is:";
	for(vector<string>::iterator it = ip_buf.begin(); it != ip_buf.end(); ++it)
		cout << *it << endl;

	if(pDoc == NULL)
		pDoc = OpenXML(Config_file);
	if(pDoc == NULL) {
		#ifdef _debug_
		cout << "				Open XML file " << Config_file << " failed" << endl;
		#endif
		return -1;
	}
//	xmlNodePtr &doc = pDoc;

	xmlNodePtr curNode = xmlDocGetRootElement(pDoc);

	//make sure the file isn't empty
	if(curNode == NULL) {
		#ifdef _debug_
		cout << "				File format error: the configuration file is empty" << endl;
		#endif
		xmlFreeDoc(pDoc);
		pDoc = NULL;
		return -1;
	}

	//check if the root's name is Configuration
	if(xmlStrcmp(curNode->name,BAD_CAST"Configuration")) {
		#ifdef _debug_
		cout << "				File format error: the root's name is error" << endl;
		#endif
		xmlFreeDoc(pDoc);
		pDoc = NULL;
		return -1;
	}

	//find the node called "Castmode"
	curNode = curNode->children;
	while(curNode != NULL) {
		if(!xmlStrcmp(curNode->name,BAD_CAST"Castmode")) {
//			xmlNodeSetContent(curNode,BAD_CAST(str_fre.c_str()));
			break;
		}
		curNode = curNode->next;
	}
	if(curNode == NULL) {
		#ifdef _debug_
		cout << "				Can't find the node Castmode" << endl;
		#endif
		xmlFreeDoc(pDoc);
		pDoc = NULL;
		return -1;
	}
	xmlNodePtr castmodeNode = curNode;

	//find number and modify it
	stringstream sstr;
	sstr << ip_buf.size();
	curNode = curNode->children;
	if(xmlStrcmp(curNode->name,BAD_CAST"number")) {
		#ifdef _debug_
		cout << "				File format error: can't find the node number" << endl;
		#endif
		xmlFreeDoc(pDoc);
		pDoc = NULL;
		return -1;
	}
	xmlNodeSetContent(curNode,BAD_CAST((sstr.str()).c_str()));
	curNode = curNode->next;

	//delete all the exsiting IP, then add new ones
	while(curNode != NULL) {
		xmlNodePtr tmpNode = curNode->next;
		xmlUnlinkNode(curNode);
		xmlFreeNode(curNode);
		curNode = tmpNode;
	}

	for(vector<string>::size_type i = 0; i != ip_buf.size(); ++i) {
		string node_name("IP");
		node_name += ('0' + i + 1);
		//add the IP
		xmlNewTextChild(castmodeNode,NULL,BAD_CAST(node_name.c_str()),BAD_CAST(ip_buf[i].c_str()));
	}
	xml_flag = true;
	cout << "				The cast mode has be changed." << endl;
	return 0;
}*/

/**
 * 该函数弃用
 */
/*int handle_MAC()
{
	//add code for MAC here
    if(ifcfg.size() == 0) {
        if(Read_ifcfg(ifcfg_file) < 0) {
	    #ifdef _debug_
            cout << "				Please make sure the file " << ifcfg_file << " exist!" << endl;
	    #endif
            return -1;
        }
    }
    cout << "				Please input a legal MAC address, " << endl;
    cout << "				such as 00:0C:29:67:5A:F7" << endl;
    cout << "				>>>";
    string str;
    if(input_mac_address(str) < 0)
    {
        cout << "				Your input is illegal. Please provide a legal MAC adress, " << endl;
		cout << "				such as 00:0C:29:67:5A:F7" << endl;
        return -1;
    }
    ip_flag = true;
    change_property(ifcfg,"HWADDR",str.c_str());
	cout << "				change MAC address successfully." << endl;
	return 0;
}*/

/************************************************************************/
/*

该函数弃用

*/
/************************************************************************/
/*int handle_password(void)
{
	#ifdef _debug_
	cout << "				Calling the system function passwd to change the password..." << endl;
	#endif
	int status;
	if((status = system("passwd")) < 0) {
		#ifdef _debug_
		cout << "				System call the \"passwd\" failed!" << endl;
		#endif
		return -1;
	}
	cout << "				The password has been changed successfully!" << endl;
	return 0;
}*/

/************************************************************************/
/*
input a legal MAC address
the format must agree with **:**:**:**:**:**such as 00:0C:29:67:5A:F7
return:
0:	input a MAC address successfully
-1:	MAC illegal
-2:	q, quit
该函数已经弃用
*/
/************************************************************************/
/*static int input_mac_address(string &str)
{
    string t_str;
    getline(cin,t_str);
    while (t_str.empty())
    {
        cin.clear();
        while(cin.peek() == '\n')
            cin.ignore();
        getline(cin,t_str);
    }
    string::iterator it = t_str.begin();

    //get rid of the space and enter at the beginning of the string
    while(*it == ' ' || *it == '\n')
        ++it;

    //quit
    if(*it == 'q')
        return -2;

    str.clear();
    str.insert(str.end(),it,t_str.end());

    //add the checking format code here
    //first, check the position and number of '.'
    vector<string::iterator> it_point;
    it_point.push_back(str.begin());
    it = str.begin();
    while(it != str.end()) {
        if((*it >= '0' && *it <= '9') || (*it >= 'a' && *it <= 'f') || (*it >= 'A' && *it <= 'F'))
            ++it;
        else if(*it == ':')
            it_point.push_back(++it);
        else
            return -1;
    }
    it_point.push_back(str.end());
    if(it_point.size() != 7)
        return -1;

    return 0;
}*/
